package org.zhangchao.poi.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import org.zhangchao.poi.excel.common.ExcelEnum;
import org.zhangchao.poi.excel.common.XCell;
import org.zhangchao.poi.excel.create.ExcelBaseCreate;
import org.zhangchao.poi.excel.create.ExcelCreatable;
import org.zhangchao.poi.excel.create.ExcelProcessModelCreate;
import org.zhangchao.poi.excel.entity.User;
import org.zhangchao.poi.excel.exception.ExcelException;
import org.zhangchao.poi.excel.operate.ExcelBaseOperate;
import org.zhangchao.poi.excel.operate.ExcelBuildModelOperate;
import org.zhangchao.poi.excel.operate.ExcelProcessModelOperate;
import org.zhangchao.poi.excel.process.ExcelBaseProcessor;
import org.zhangchao.poi.excel.process.ExcelBuildModelProcessor;
import org.zhangchao.poi.excel.process.ExcelProcessable;

/**
 * Excel 操作工具类
 * @author zhangchao
 *
 */
public class ExcelUtil<E> {

	/** Excel处理器 */
	private Object excelHandle;
	
	/** 判断excelHandle是否实现ExcelProcessable */
	private boolean isExcelProcessable;
	
	/** 判断excelHandle是否实现ExcelCreatable */
	private boolean isExcelCreatable;
	
	/**
	 * 
	 */
	private ExcelUtil() {
		
	}
	
	/**
	 * 初始化参数
	 */
	private void init() {
		if(excelHandle instanceof ExcelProcessable) {
			isExcelProcessable = true;
		}else {
			isExcelProcessable = false;
		}
		if(excelHandle instanceof ExcelCreatable) {
			isExcelCreatable = true;
		}else {
			isExcelCreatable = false;
		}
	}
	
	/**
	 * 构建一个Excel处理器用于Excel解析（SAX）（导入使用）
	 * @param file
	 * @param type
	 * @param clazz
	 * @param headerdStartCell
	 * @param dataStartCell
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildProcessor(File file, ExcelEnum type,
			Class<?> clazz, XCell headerdStartCell, XCell dataStartCell) throws Exception {
		ExcelUtil excelUtil = new ExcelUtil();
		excelUtil.excelHandle = new ExcelBuildModelProcessor(file, type, clazz, headerdStartCell, dataStartCell);
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel解析（SAX）（导入使用）
	 * @param is
	 * @param type
	 * @param clazz
	 * @param headerdStartCell
	 * @param dataStartCell
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static ExcelUtil<?> buildProcessor(InputStream is, ExcelEnum type,
			Class<?> clazz, XCell headerdStartCell, XCell dataStartCell) throws Exception {
		ExcelUtil<?> excelUtil = new ExcelUtil();
		excelUtil.excelHandle = new ExcelBuildModelProcessor<User>(is, type, clazz, headerdStartCell, dataStartCell);
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel操作（DOM）（导入 使用）
	 * @param file
	 * @param type
	 * @param clazz
	 * @param headerdStartCell
	 * @param dataStartCell
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildOperate(File file,	Class<?> clazz, XCell headerdStartCell, XCell dataStartCell) throws Exception {
		ExcelUtil excelUtil = new ExcelUtil();
		excelUtil.excelHandle = new ExcelBuildModelOperate(file, clazz, headerdStartCell, dataStartCell);
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel操作（DOM）（导入 使用）
	 * @param is
	 * @param type
	 * @param clazz
	 * @param headerdStartCell
	 * @param dataStartCell
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildOperate(InputStream is, Class<?> clazz, XCell headerdStartCell, XCell dataStartCell) throws Exception {
		ExcelUtil excelUtil = new ExcelUtil();
		excelUtil.excelHandle = new ExcelBuildModelOperate(is, clazz, headerdStartCell, dataStartCell);
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel操作（DOM）（导出 使用）
	 * @param type
	 * @param templateFile
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildOperate(ExcelEnum type, File templateFile, Class<?> clazz) throws Exception {
		ExcelUtil excelUtil = new ExcelUtil();
		if(null == templateFile) {
			excelUtil.excelHandle = new ExcelProcessModelOperate(type, clazz);
		} else {
			excelUtil.excelHandle = new ExcelProcessModelOperate(type, templateFile, clazz);
		}
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel操作（DOM）（导出 使用）
	 * @param type
	 * @param templateInp
	 * @param clazz
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildOperate(ExcelEnum type, InputStream templateInp, Class<?> clazz) throws Exception {
		ExcelUtil excelUtil = new ExcelUtil();
		if(null == templateInp) {
			excelUtil.excelHandle = new ExcelProcessModelOperate(type, clazz);
		} else {
			excelUtil.excelHandle = new ExcelProcessModelOperate(type, templateInp, clazz);
		}
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel创建（xlsx导出使用）
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static ExcelUtil buildCreate(Class<?> clazz, File templateFile) {
		ExcelUtil excelUtil = new ExcelUtil();
		if(null == templateFile) {
			excelUtil.excelHandle = new ExcelProcessModelCreate(clazz);
		}else {
			excelUtil.excelHandle = new ExcelProcessModelCreate(clazz, templateFile);
		}
		excelUtil.init();
		return excelUtil;
	}
	
	/**
	 * 构建一个Excel处理器用于Excel创建（xlsx导出使用）
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static ExcelUtil buildCreate(Class<?> clazz, InputStream is) {
		ExcelUtil excelUtil = new ExcelUtil();
		if(null == is) {
			excelUtil.excelHandle = new ExcelProcessModelCreate(clazz);
		}else {
			excelUtil.excelHandle = new ExcelProcessModelCreate(clazz, is);
		}
		excelUtil.init();
		return new ExcelUtil();
	}
	
	/**
	 * 
	 */
	public void create() {
		if(isExcelCreatable) {
			((ExcelCreatable)excelHandle).create();
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @param sheetName
	 */
	public void create(String sheetName) {
		if(isExcelCreatable) {
			((ExcelCreatable)excelHandle).create(sheetName);
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @param stream
	 * @throws IOException
	 */
	public void write(OutputStream stream) throws IOException {
		if(isExcelCreatable) {
			((ExcelCreatable)excelHandle).write(stream);
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @param sheetIndex
	 * @throws Exception
	 */
	public void processOneSheet(int sheetIndex) throws Exception {
		if(isExcelProcessable) {
			((ExcelProcessable)excelHandle).processOneSheet(sheetIndex);
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @throws Exception
	 */
	public void processAllSheets() throws Exception {
		if(isExcelProcessable) {
			((ExcelProcessable)excelHandle).processAllSheets();
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}
	
	/**
	 * 
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<E> getData() {
		if(isExcelProcessable) {
			if(excelHandle instanceof ExcelBaseOperate) {
				return ((ExcelBaseOperate<E>)excelHandle).getData();
			}else {
				return ((ExcelBaseProcessor<E>)excelHandle).getData();
			}
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @param data
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void setData(List<?> data) {
		if(isExcelCreatable) {
			if(excelHandle instanceof ExcelBaseOperate) {
				((ExcelBaseOperate)excelHandle).setData(data);
			}else {
				((ExcelBaseCreate)excelHandle).setData(data);
			}
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

	/**
	 * 
	 * @param labelMap
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void setLabelMap(Map<String, String> labelMap) {
		if(isExcelCreatable) {
			if(excelHandle instanceof ExcelBaseOperate) {
				((ExcelBaseOperate)excelHandle).setLabelMap(labelMap);
			}else {
				((ExcelBaseCreate)excelHandle).setLabelMap(labelMap);
			}
		}else {
			throw new ExcelException("不能执行这个方法");
		}
	}

}
